/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ru.niir.goodfil.ui;

import com.sun.rave.web.ui.appbase.AbstractPageBean;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import ru.niir.goodfil.audit.client.AuditService;
import ru.niir.goodfil.db.audit.helpers.AuditHelper;
import ru.niir.goodfil.db.handlers.Goodfil;
import ru.niir.goodfil.ui.audit.AuditBean;
import ru.niir.goodfil.ui.audit.JsfAuditHelper;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static ru.niir.goodfil.utils.Utils.s;

/**
 * Базовый request бин.
 */
public class PageBean extends AbstractPageBean {
    private AuditHelper auditHelper = new JsfAuditHelper();

    private static final Logger _logger = Logger.getLogger(PageBean.class);

    /**
     * Наименование основного сетевого бина
     */
    private final static String SESSION_BEAN_KEY = "SessionBean";

    /**
     * Наименование бина, отвечающего за разграничение прав пользователей
     */
    private final static String SECURITY_BEAN_KEY = "SecurityBean";

    /**
     * Наименование бина, отвечающего за протоколирование
     */
    private final static String AUDIT_BEAN_KEY = "AuditBean";


    /**
     * Объект для взаимодействия с БД
     */
    private Goodfil gf;

    public synchronized Goodfil gf() {
        return gf;
    }

    /**
     * Конструктор
     */
    public PageBean() {
        gf = getSessionBean().getGoodfil();

        assert gf != null;
    }

    /**
     * Получить сессионный бин
     */
    protected SessionBean getSessionBean() {
        return (SessionBean) getBean(SESSION_BEAN_KEY);
    }

    /**
     * Получить бин, отвечающий за разграничение прав пользователей
     */
    protected SecurityBean getSecurityBean() {
        return (SecurityBean) getBean(SECURITY_BEAN_KEY);
    }

    /**
     * Добавить сообщение в faces контекст
     *
     * @param context   контекст (взять из функции-валидатора)
     * @param component компонент (взять из функции-валидатора)
     * @param message   сообщение об ошибке
     */
    protected void facesError(FacesContext context, UIComponent component, String message) {
        assert context != null;
        assert component != null;
        assert message != null;
        assert !isEmpty(message);

        context.addMessage(component.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR, message, ""));
    }

    protected HttpServletRequest request() {
        return (HttpServletRequest) getFacesContext().getExternalContext().getRequest();
    }

    protected HttpServletResponse response() {
        return (HttpServletResponse) getFacesContext().getExternalContext().getResponse();
    }

    /**
     * Установить сообщение об ошибке.
     *
     * @param message ошибка
     */
    protected boolean facesError(String message) {
        getFacesContext().addMessage("", new FacesMessage(FacesMessage.SEVERITY_ERROR, message, ""));
        return false;
    }

    /**
     * Установить информационное сообщение.
     *
     * @param message информация
     */
    protected void facesInfo(String message) {
        getFacesContext().addMessage("", new FacesMessage(FacesMessage.SEVERITY_INFO, message, ""));
    }

    /**
     * Возвращает информацию о наличии ошибок.
     *
     * @return <b>true</b>-есть</br> <b>false</b>-нет
     */
    protected boolean hasFacesErrors() {
        return getFacesContext().getMaximumSeverity() == FacesMessage.SEVERITY_ERROR;
    }

    /**
     * Возвращает
     *
     * @return
     */
    public boolean getHasFacesErrors() {
        return hasFacesErrors();
    }

    public String getFacesMessagesAsString() {
        StringBuilder sb = new StringBuilder();
        Iterator<FacesMessage> i = getFacesContext().getMessages();
        while (i.hasNext()) {
            FacesMessage facesMessage = i.next();
            if (facesMessage.getSeverity() == FacesMessage.SEVERITY_ERROR ||
                    facesMessage.getSeverity() == FacesMessage.SEVERITY_FATAL) {
                sb.append(facesMessage.getSummary());
                sb.append("\n");
            }
        }
        return sb.toString();
    }

    protected void sendRedirect(String url) {
        try {
            response().sendRedirect(url);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Устанавливает в список объект с ключем.
     *
     * @param key ключ
     * @param o   объект
     */
    protected void putObject(String key, Object o) {
        getSessionBean().putObject(key, o);
    }

    /**
     * Возвращает объект по его ключу.
     *
     * @param key ключ
     * @return объект
     */
    protected Object takeObject(String key) {
        return getSessionBean().takeObject(key);
    }

    /**
     * -------------------------------------------------------------------------
     * ----------SECTION ВАЛИДАЦИЯ НА КОЛЕНКЕ ----------
     * -------------------------------------------------------------------------
     */

    /**
     * Сообщение об ошибке
     */
    private String val;

    /**
     * Установить сообщение об ошибке.
     *
     * @param msg сообщение
     */
    public final void validated(String msg) {
        if (msg != null) _logger.debug("Validation error: " + msg);
        this.val = msg;
    }

    /**
     * Возвращает наличие ошибки.
     *
     * @return <b>true</b>-есть</br> <b>false</b>-нет
     */
    public final boolean isValOk() {
        return StringUtils.isEmpty(val);
    }

    /**
     * Возщвращает сообщение ошибки.
     *
     * @return сообщение
     */
    public final String getVal() {
        return val;
    }

    /*
    --------------------------------------------------------------------------------------------------------
     */

    public SessionString SessionString(String name) {
        return new SessionString(getSessionBean(), name, true);
    }

    public static class SessionString {
        private SessionBean sessionBean;

        private boolean denyEmptyValues = false;

        private SessionBean getSessionBean() {
            return sessionBean;
        }

        private final String name;

        public SessionString(SessionBean sessionBean, String name) {
            this.sessionBean = sessionBean;
            this.name = name;
            setValue("");
        }

        public SessionString(SessionBean sessionBean, String name, boolean denyEmptyValues) {
            this.sessionBean = sessionBean;
            this.name = name;
            this.denyEmptyValues = denyEmptyValues;

            setValue("");
        }

        public SessionString(SessionBean sessionBean, String name, String value) {
            this.sessionBean = sessionBean;
            this.name = name;
            setValue(value);
        }

        public SessionString(SessionBean sessionBean, String name, String value, boolean denyEmptyValues) {
            this.sessionBean = sessionBean;
            this.name = name;
            this.denyEmptyValues = denyEmptyValues;

            setValue(value);
        }

        public String getValue() {
            return getSessionBean().getStringVariable(name);
        }

        public void setValue(String value) {
            if (isBlank(value) && denyEmptyValues) return;

//            _logger.debug("Session STRING variable `" + name + "` now has value " + s(value));
            getSessionBean().setVariable(name, s(value));
        }

        public void clear() {
//            _logger.debug("Session STRING variable `" + name + "` now has value of empty string");
            getSessionBean().setVariable(name, "");
        }
    }

    public static class SessionLong {
        private SessionBean sessionBean;

        private SessionBean getSessionBean() {
            return sessionBean;
        }

        private final String name;

        public SessionLong(SessionBean sessionBean, String name) {
            this.sessionBean = sessionBean;
            this.name = name;
            setValue(0);
        }

        public SessionLong(SessionBean sessionBean, String name, long value) {
            this.sessionBean = sessionBean;
            this.name = name;
            setValue(value);
        }

        public long getValue() {
            return getSessionBean().getLongVariable(name);
        }

        public void setValue(long value) {
            _logger.debug("Session STRING variable `" + name + "` now has value " + value);
            getSessionBean().setVariable(name, value);
        }
    }

    public static class SessionInt {
        private SessionBean sessionBean;

        private SessionBean getSessionBean() {
            return sessionBean;
        }

        private final String name;

        public SessionInt(SessionBean sessionBean, String name) {
            this.sessionBean = sessionBean;
            this.name = name;
            setValue(0);
        }

        public SessionInt(SessionBean sessionBean, String name, int value) {
            this.sessionBean = sessionBean;
            this.name = name;
            setValue(value);
        }

        public int getValue() {
            return getSessionBean().getIntVariable(name);
        }

        public void setValue(int value) {
            _logger.debug("Session INT variable `" + name + "` now has value " + value);
            getSessionBean().setVariable(name, value);
        }
    }

    //
    //  Dynamic params ----------------------------------------------------------------------
    //

    private Map params = new HashMap();

    public Map getParams() {
        return params;
    }

    public void setParams(Map params) {
        this.params = params;
    }

    protected long Long(String s) {
        return new Long((String) params.get(s));
    }

    protected String String(String s) {
        return (String) params.get(s);
    }

    protected int Int(String s) {
        return new Integer((String) params.get(s));
    }

    protected float Float(String s) {
        return new Float((String) params.get(s));
    }

    //  -------------------------------------------------------------------------------------

    protected AuditService getAuditService() {
        return getAuditBean().getAuditService();
    }

    protected AuditBean getAuditBean() {
        return (AuditBean) getBean(AUDIT_BEAN_KEY);
    }

    public AuditHelper getAuditHelper() {
        return auditHelper;
    }
}